import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.util.*;
import java.lang.Object.*;
/**
 * Clase Link para hacer representacion a nuestro Heroe que es controlado por el jugador
 * @author Programación Orientada a Objetos (Adrian Cerda Cerda , Jorge Armando Tovar Ojeda)
 * @version Maze of Souls (20 de noviembre del 2012)
 */
 
public class Link extends Actor
{
   
    private long relojUno = 0;// Contador para el cambio de imagenes y duracón en lanzar una flecha
    private long relojDos = 0;// Contador para el cambio de imagenes
    private long relojTres = 0;// Contador para el cambio de imagenes
    private static int dir = 1; // variable para la dirreción en que va nuestro heroe
    private int tiempo=40;// contador de tiempo
    private static int volteando = 1;// variable para saber asia donde nuestro Hero esta volteando
    private static int imagenActual=0;// para la saber cual es la imagen actual que se tiene
    private static final int Q =  0;//cuando esta parado nuestro Heroe
    private static final int D =  1;// Si nuestro heroe va asía abajo
    private static final int U =  2;// Si nuestro heroe va asía arriva
    private static final int R =  3;// Si nuestro heroe va asía la derecha
    private static final int L =  4;// Si nuestro heroe va asía la izquierda
    private static final int S =  5;// cuando 
    private int I=R;// para el indice de la imagen 
    static final int NUM_IMAG=30;// numero de imagenes de nuestro heroe
    private GreenfootImage[] lasImagenes = new GreenfootImage[NUM_IMAG];// arreglo de las imagenes de nuetro heroe
    private boolean band  = false;// bandera para si se puede o no mover nuestro Heroe
    private Fondo w= (Fondo)super.getWorld();// para obtener el Mundo
    private int llave=1;//lleva el conteo de la llave
  
    /**
     * Metodo que hace todos los movimientos de nuestro heroe
     */
    public void act() 
    {
       tocarLlave();
       tocarCaja();
        if(puedeAvanzar3()&& puedeAvanzar2())
             mover();
         imagen();
         cambia();
        
         
    }    
    /**
     * Para checar el precionado de las teclas y agregar la dirreción que va a tomar 
     */
    public void mover()
    {
        if(Greenfoot.isKeyDown("right")){
           volteando = dir = R;
        }
        if(Greenfoot.isKeyDown("left")){
            volteando = dir = L;
        }
        if(Greenfoot.isKeyDown("up")){
           volteando =  dir = U;
        }
        if(Greenfoot.isKeyDown("down")){
            volteando = dir = D;
            
        }
        
        if(Greenfoot.isKeyDown("space")|| band == true ){
            if(w.energia>0)
               band = dispara();
        }
        if(!(Greenfoot.isKeyDown("space")))
        moverDireccion();
    }
    /**
     * Cambia las imagenes de nuestro Heroe
     */
    public void imagen()
    {
        setImage(lasImagenes[I]);
    }
    /**
     * Metodo para indicar cuanto camine dependiendo la dirreción
     */
    public void moverDireccion(){
        if(dir==D)
           camina(1, 0, 2);
        else
        if(dir==U)
          camina(6, 0, -2);
        else
        if(dir==R)
          camina(11, 2, 0);
        else
        if(dir==L)
          camina(16,-2, 0);
     }
     /**
      * Metodo para hacer el caminado de nuestro Heroe e intercabio de imagenes
      * @param i  recibe la imagen inicial 
      * @param x para mover en el eje de las X
      * @param y para mover en el eje de las Y
      */
     public void camina(int i, int x, int y)
     {
           int aux=i;
            if(imagenActual!=2)
            {
                I=i;
              
                if(System.currentTimeMillis()-relojDos>tiempo)
                {
                    I=i+1;
                    relojDos=System.currentTimeMillis();
                    imagenActual=2;
                 
                }
                
            }
             if(imagenActual!=1)
            {
                I=i+2;
                if(System.currentTimeMillis()-relojTres>(tiempo*2))
                {
                    I=i+3;
                    relojTres=System.currentTimeMillis();
                    imagenActual=1;
                }
                
            }
            if(System.currentTimeMillis()-relojUno>(tiempo*3))
            {
                I=aux-1;
                relojUno=System.currentTimeMillis();
                dir=Q;
               
            }
        
            this.setLocation(getX()+x,getY()+y);    
     }
    /**
     * Constructor Link para crear nuestro heroe e inicializar el arreglo de todas sus imagenes
     * @param p recibe la posición inicial de nuestro Heroe
     */
    public Link(int pos)
    {        
         for(int i=0; i<NUM_IMAG; i++)
           lasImagenes[i]=new GreenfootImage("Link"+i+".PNG");
         I=pos;
    }
    /**
     * Metodo para mandar hacer el disparo dependiendo la posición 
     * @return band para saber si se mando llamar este metodo
     */
    public boolean dispara()
    {
       switch(volteando)
       {
           case D:
                     disparo(20,0,0,5);
                  break;
            case R:
                    disparo(23,10,5,0);
                  break;
            case L:
                    disparo(25,15,-5,0);
                  break;
            case U:
                    disparo(24,5,0,-12);
                  break;
        }
        
        
        return band;
    } 
    /**
    * Metodo que hace el disparo (Lanza una flecha)
    * @param il imagen inicial en la que esta mi heroe
    * @param il imagen en modo de disparo
    * @param x pocisíon inicial donde aparece la flecha en x
    * @param y posición inicial donde aparece la flecha en y
    */
    public void disparo(int i1, int i2, int x, int y)
    {
        I=i1;
         band=true;
         if(System.currentTimeMillis()-relojUno>2200)
            {
                I=i2;
                relojUno=System.currentTimeMillis();
                Greenfoot.playSound("wchoose.wav");
                Flecha f= new Flecha(volteando);
                Fondo w= (Fondo)super.getWorld();
                w.addObject(f, getX()+x, getY()+y);
                w.cambiaEnergia(-1);
                band=false;
            }
    }
    /**
     * Metodo para poder avanzar mientras no intersecte con algún obstaculo
     *@return true si puede avanzar o false si no
     */
    public boolean puedeAvanzar()
    {
        List l= getIntersectingObjects(Obstaculo.class);
       
        if(l.isEmpty())
        {
            return true;
        }
        else
        {
          if(moverPosicion());
          return false;
        }
        
    }
     /**
     * Metodo para poder avanzar mientras no intersecte con algún Enemigo
     *@return true si puede avanzar o false si no
     */
   public  boolean puedeAvanzar2()
    {
       
        List e= getIntersectingObjects(Enemigo.class);
        if(e.isEmpty()/*|| e.isEmpty()*/)
        {
            return true;
        }
        else
        {
          if(moverPosicion());
          return false;
        }
        
    }
    
    /** 
     * Metodo para mover de pocisión en caso de que haya chocado con algun objeto
     * @return false si no puede moverse y true cuando ya puede
     */
    public boolean moverPosicion()
    {
        boolean band=false;
        int x=getX();
        int y=getY();
        switch(volteando)
        {
            case D:
                   this.setLocation(x,y-5);
                     band=true;
                   break;
            case R:
                   this.setLocation(x-5,y);
                     band=true;
                   break;
            case L:
                   this.setLocation(x+5,y);
                     band=true;
                   break;
            case U:
                   this.setLocation(x,y+5);
                     band=true;
                   break;
          
            
        }
        return band;
    }
    /**
     * Metodo para el cambio de niveles
     * dependiendo si se han juntado todos los tesoros del nivel,
     * si se han destruido todas las cajas,
     * si se ha recojido la llave y si esta llave corresponde a la 
     * puerta que se quiere abrir
     */
    public void cambia()
    {
        Mensaje m; 
       PuertaMayor pM;
        pM=(PuertaMayor)super.getOneIntersectingObject(PuertaMayor.class);
       
        if(pM!=null)
        {
             Fondo f= (Fondo)super.getWorld();
             if(f!=null)
           
             if(pM.regresaPuerta()== f.regresaLlave()&& 
                           f.regresaLlave()!= llave&&
                           f.regresaTesoro()== f.regresaN() && f.regresaCaja()==0)
             {
                
                llave++; 
               
                if(pM.regresaPuerta()==5)
                {
                    Greenfoot.stop();
                    m= new Mensaje("FELICIDADES"+"\n"+"GANASTTE",40);
                    f.addObject(m,350,300);
                    Greenfoot.delay(200);
                    f.menuOpsion(0,0);
                }
                else
                {
                 f.eliminaObjetos();
                 f.cambiaMapa(pM.regresaPuerta());
                }
            }
            else
              {
                  m = new Mensaje("La llave no "+"\n"+"coincide o te "+ "\n"+ "falta juntar" + "\n"+"los Tesoros", 15);
                  f.addObject(m, getX(), getY());
                  m.imprime();
                  Greenfoot.delay(100);
                  f.removeObject(m);
                  moverPosicion(); 
                   
              }
        }
    }
    /**
     * cambia el indice del arreglo para hacer el cambio de la imagen
     * @param i la imagen que se va a poner
     */
    public void cambiaImagen(int i)
    {
        I= i;
    }
    /**
     * @return I regresa el indice de la imagen para saber cual esta activa
     */
    public int regresaImagen()
    {
        return I;
    }
    /**
     * Verifica de otra manera si se puede mover si intersecta con un obstaculo
     * @return true si ya puede avanzar o false si no puede
     */
     public boolean puedeAvanzar3()
    {
        Actor p;
       p= getOneObjectAtOffset(-8,0,Obstaculo.class);
        if(p!=null)
        {
           setLocation(getX()+5, getY());
           return false;
         }
        p= getOneObjectAtOffset(8,0,Obstaculo.class);
         if(p!=null)
        {
           setLocation(getX()-5, getY());
           return false;
        }
       
        p= getOneObjectAtOffset(0,10,Obstaculo.class);
         if(p!=null)
        {
           setLocation(getX(), getY()-5);
           return false;
        }
         p= getOneObjectAtOffset(0,-10,Obstaculo.class);
         if(p!=null)
        {
           
           setLocation(getX(), getY()+5);
           return false;
        }
       
        else
       {
          return true;
        }
    }
    /**
     * Metodo para saber cuando se encontro la llave
     */
    public void tocarLlave()
    {
        Actor l= getOneIntersectingObject(Llave.class);
        if(l!= null)
        {
            Fondo f= (Fondo)super.getWorld();
            f.cambiaLlave();
            if(f!=null)
            f.removeObject(l);
        }
    }
    /**
     * Metodo que verifica si ha chocado con una caja 
     */
    public void tocarCaja()
    {
         Actor c= getOneIntersectingObject(Caja.class);
         if(c!=null)
         {
             moverPosicion();
         }
    }
    
    
}
